iT邦幫忙

2022 iThome 鐵人賽

DAY 21
0

MUI 的 Accordion 支援兩種行為:

  • 每個 Accordion 元件的開闔狀態各自獨立:當畫面上有複數個 Accordion 元件時,開啟 Accordion 一號不會影響畫面上其餘的 Accordion 狀態
  • 當畫面上有複數個 Accordion 元件時,同一時間只會有一個 AccordionBody 被展開

而昨天暫時跳過的變數 hasOpenFromProps 就是為了實現第二種功能,以下是解說時段。

成品

原始碼
展示

開發思路

首先檢查是否有透過 props 傳入變數 open

const hasOpenFromProps = useMemo(
  () => Object.keys(props).includes('open'),
  [props]
);

若有,則使用 props.open 來控制 AccordionBody 開闔,反之則使用 Accordion 內部的 useState 變數 localOpen 來管理狀態:

const openToUse = useMemo(
  () => (hasOpenFromProps ? open : localOpen),
  [hasOpenFromProps, open, localOpen]
);

Accordion 透過 props.open 控制開闔時,不使用 Accordion 元件內部的 toggleAccordion 來驅動開闔狀態:

setTitleElement(
  React.cloneElement(childElement, {
    open: openToUse,
    onClick: hasOpenFromProps ? undefined : toggleAccordion,
    accordionTitleClass: classes.title,
  })
);

使用方式:

function AccordionsDemo(): React.ReactElement {
  const [currentOpen, setCurrentOpen] = useState<number>(0);

  // 當使用者點擊各個 Accordion 元件時,設定當下需要展開的 AccordionBody
  const openAccordion = (panelNumber: number) => () => {
    if (panelNumber === currentOpen) {
      setCurrentOpen(0);
    } else {
      setCurrentOpen(panelNumber);
    }
  };

  // 每一個 Accordion 透過 props.open 比對 currentOpen 來控制當下是哪一個 AccordionBody 需要展開
  return (
    <Stack>
      <Accordion onClick={openAccordion(1)} open={currentOpen === 1}>
        <AccordionTitle>title 1</AccordionTitle>
        <AccordionBody>body 1</AccordionBody>
      </Accordion>
      <Accordion onClick={openAccordion(2)} open={currentOpen === 2}>
        <AccordionTitle>title 2</AccordionTitle>
        <AccordionBody>body 2</AccordionBody>
      </Accordion>
      <Accordion onClick={openAccordion(3)} open={currentOpen === 3}>
        <AccordionTitle>title 3</AccordionTitle>
        <AccordionBody>body 3</AccordionBody>
      </Accordion>
    </Stack>
  );
}

自評

元件開闔的邏輯很單純,如果設計稿上 Accordion 的外觀與既有的第三方元件庫有落差的話,可以考慮自幹。

但上述的情境會帶出另一個問題:「那麼當初在選型時,是否沒有顧慮到該元件庫能與現行的設計風格搭配,才會出現元件庫不易配合設計稿的狀況」。

小結論:除了懷疑設計師為何會畫出不好實作的前端介面時,問題也有可能出在工程師挑選了不容易搭配現行設計的框架來開發。


上一篇
day20: Accordion
下一篇
day22: TransitionEffect, useDelayUnmount
系列文
我們可以不要 component library 了嗎?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言